/**************************************************************************************************
**                                                                                               **
**  文件名称:  dal_can_drv.c                                                                     **
**  版权所有:  CopyRight @ Xiamen Yaxon NetWork CO.LTD. 2017                                     **
**  文件描述:  CAN的驱动管理                                                                     **
**  ===========================================================================================  **
**  创建信息:  | 2017-8-3 | LEON | 创建本模块                                                    **
**  ===========================================================================================  **
**  修改信息:  单击此处添加....                                                                  **
**************************************************************************************************/
#include "dal_include.h"
#include "dal_can_drv.h"

/*************************************************************************************************/
/*                           模块宏定义                                                          */
/*************************************************************************************************/
#define _COMOPEN             0x01
#define _SENDING             0x80

#define MAX_CAN_SEND         30
#define MAX_CAN_RECV         50

/*************************************************************************************************/
/*                           数据结构定义                                                        */
/*************************************************************************************************/
typedef struct {
    INT8U             pos;
    INT8U             used;
    INT8U             max;
    CAN_DATA_T       *pmsg;
} CAN_QUEUE_T;

typedef struct {
    INT8U             status;
    CAN_QUEUE_T       rx_buf;
    CAN_QUEUE_T       tx_buf;
} CAN_CTRL_T;

/*************************************************************************************************/
/*                           模块静态变量定义                                                    */
/*************************************************************************************************/
static CAN_CTRL_T s_canctrlbk;
static CAN_DATA_T s_can_rxbuf[MAX_CAN_RECV];
static CAN_DATA_T s_can_txbuf[MAX_CAN_SEND];

/**************************************************************************************************
**  函数名称:  LeftOfLoopBuffer
**  功能描述:  获取循环缓冲区中剩余的空间
**  输入参数:  loop:    循环缓冲区管理结构体
**  输出参数:  无
**  返回参数:  剩余空间字节数
**************************************************************************************************/
INT32U LeftOfLoopBuffer(CAN_QUEUE_T *loop)
{
    INT32U temp;
    
    ENTER_CRITICAL();
    temp = loop->max - loop->used;
    EXIT_CRITICAL();
    
    return temp;
}

/**************************************************************************************************
**  函数名称:  UsedOfLoopBuffer
**  功能描述:  获取循环缓冲区中已使用空间
**  输入参数:  loop:    循环缓冲区管理结构体
**  输出参数:  无
**  返回参数:  已使用空间字节数
**************************************************************************************************/
static INT32U UsedOfLoopBuffer(CAN_QUEUE_T *loop)
{
    INT32U temp;
    
    ENTER_CRITICAL();
    temp = loop->used;
    EXIT_CRITICAL();
    
    return temp;
}

/**************************************************************************************************
**  函数名称:  UsedOfLoopBuffer_INT
**  功能描述:  获取循环缓冲区中已使用空间
**  输入参数:  loop:    循环缓冲区管理结构体
**  输出参数:  无
**  返回参数:  已使用空间字节数
**************************************************************************************************/
static INT32U UsedOfLoopBuffer_INT(CAN_QUEUE_T *loop)
{
    return loop->used;
}

/**************************************************************************************************
**  函数名称:  ReadLoopData
**  功能描述:  从循环缓冲区中读取一帧数据
**  输入参数:  loop:    循环缓冲区管理结构体
**  输出参数:  data:    读取数据
**  返回参数:  成功返回TRUE,失败返回FALSE
**************************************************************************************************/
static BOOLEAN ReadLoopData(CAN_QUEUE_T *loop, CAN_DATA_T *data)
{
    INT16U used, pos;
    
    ENTER_CRITICAL();
    used = loop->used;
    pos  = loop->pos;
    EXIT_CRITICAL();
    
    if (used == 0) {
        return false;
    }
    
    memcpy((INT8U *)data, (INT8U *)&loop->pmsg[pos], sizeof(CAN_DATA_T));
    
    ENTER_CRITICAL();
    loop->used--;
    loop->pos++;
    if (loop->pos >= loop->max) {
        loop->pos -= loop->max;
    }
    EXIT_CRITICAL();
    return true;
}

/**************************************************************************************************
**  函数名称:  ReadLoopData_INT
**  功能描述:  从循环缓冲区中读取一帧数据
**  输入参数:  loop:    循环缓冲区管理结构体
**  输出参数:  data:    读取数据
**  返回参数:  成功返回TRUE,失败返回FALSE
**************************************************************************************************/
static BOOLEAN ReadLoopData_INT(CAN_QUEUE_T *loop, CAN_DATA_T *data)
{
    INT16U used, pos;
    
    used = loop->used;
    pos  = loop->pos;
    
    if (used == 0) {
        return false;
    }
    
    memcpy((INT8U *)data, (INT8U *)&loop->pmsg[pos], sizeof(CAN_DATA_T));
    
    loop->used--;
    loop->pos++;
    if (loop->pos >= loop->max) {
        loop->pos -= loop->max;
    }
    return true;
}

/**************************************************************************************************
**  函数名称:  WriteLoopData
**  功能描述:  往循环缓冲区中写入一帧数据
**  输入参数:  loop:   循环缓冲区管理结构体
**  输出参数:  data:   写入数据
**  返回参数:  成功返回true,失败返回false
**************************************************************************************************/
static BOOLEAN WriteLoopData(CAN_QUEUE_T *loop, CAN_DATA_T *data)
{
    INT16U used, pos;
    
    ENTER_CRITICAL();
    used = loop->used;
    pos  = loop->pos;
    EXIT_CRITICAL();
    
    if (used >= loop->max) {
        return FALSE;
    }
    
    pos += used;
    if (pos >= loop->max) {
        pos -= loop->max;
    }
        
    memcpy((INT8U *)&loop->pmsg[pos], (INT8U *)data, sizeof(CAN_DATA_T));
    
    ENTER_CRITICAL();
    loop->used++;
    EXIT_CRITICAL();
    return TRUE;
}

/**************************************************************************************************
**  函数名称:  WriteLoopData_INT
**  功能描述:  往循环缓冲区中写入一帧数据
**  输入参数:  loop:   循环缓冲区管理结构体
**  输出参数:  data:   写入数据
**  返回参数:  成功返回true,失败返回false
**************************************************************************************************/
static BOOLEAN WriteLoopData_INT(CAN_QUEUE_T *loop, CAN_DATA_T *data)
{
    INT16U used, pos;
    
    used = loop->used;
    pos  = loop->pos;
    
    if (used >= loop->max) {
        return FALSE;
    }
    
    pos += used;
    if (pos >= loop->max) {
        pos -= loop->max;
    }
        
    memcpy((INT8U *)&loop->pmsg[pos], (INT8U *)data, sizeof(CAN_DATA_T));
    
    loop->used++;
    return TRUE;
}

/**************************************************************************************************
**  函数名称:  StartCanSend
**  功能描述:  开始发送CAN数据
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static BOOLEAN StartCanSend(CAN_DATA_T *data)
{
    INT8U     mailbox;
    CanTxMsg  txmessage;
    
    txmessage.IDE   = (data->dttype == CAN_STD_FAMRE) ? CAN_ID_STD : CAN_ID_EXT;
    txmessage.StdId = (data->dttype == CAN_STD_FAMRE) ? data->id : 0x00;
    txmessage.ExtId = (data->dttype == CAN_STD_FAMRE) ? 0x00 : data->id;
    txmessage.RTR   = (data->format == CAN_DATA_FORMAT) ? CAN_RTR_DATA : CAN_RTR_REMOTE;
    txmessage.DLC = data->dlc;
    
    memcpy(txmessage.Data, data->data, 8);
    
    mailbox = CAN_Transmit((CAN_TypeDef *)CAN_BASE, &txmessage);
    
    if (mailbox == CAN_TxStatus_NoMailBox) {
        CAN_CancelTransmit((CAN_TypeDef *)CAN_BASE, 0);
        CAN_CancelTransmit((CAN_TypeDef *)CAN_BASE, 1);
        CAN_CancelTransmit((CAN_TypeDef *)CAN_BASE, 2);
        return false;
    } else {
        return true;
    }
}

/**************************************************************************************************
**  函数名称:  CAN_IrqHandle
**  功能描述:  CAN中断处理函数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void CAN_IrqHandle(void)
{
    INT8U         j, used;
    CanRxMsg      rxmessage;
    CAN_DATA_T    recvdata;
    
    if (CAN_GetFlagStatus(CAN, CAN_FLAG_FMP0) != RESET) {                      /* FIFO0 数据接收中断 */
        CAN_ClearITPendingBit(CAN, CAN_FLAG_FMP0);
        CAN_Receive(CAN, CAN_FIFO0, &rxmessage);
        
        recvdata.dttype = (rxmessage.IDE == CAN_ID_STD) ? CAN_STD_FAMRE : CAN_EXT_FAMRE;
        recvdata.id     = (rxmessage.IDE == CAN_ID_STD) ? rxmessage.StdId : rxmessage.ExtId;
        recvdata.format = (rxmessage.RTR == CAN_RTR_DATA) ? CAN_DATA_FORMAT : CAN_REMO_FORMAT;
        recvdata.dlc    = (rxmessage.DLC);
        
        for (j = 0; j < rxmessage.DLC; j++) {
            recvdata.data[j] = rxmessage.Data[j];
        }
        
        WriteLoopData_INT(&s_canctrlbk.rx_buf, &recvdata);
    }
    
    if (CAN_GetFlagStatus(CAN, CAN_FLAG_FMP1) != RESET) {                      /* FIFO1 数据接收中断 */
        CAN_ClearITPendingBit(CAN, CAN_FLAG_FMP1);
        CAN_Receive(CAN, CAN_FIFO1, &rxmessage);
        
        recvdata.dttype = (rxmessage.IDE == CAN_ID_STD) ? CAN_STD_FAMRE : CAN_EXT_FAMRE;
        recvdata.id     = (rxmessage.IDE == CAN_ID_STD) ? rxmessage.StdId : rxmessage.ExtId;
        recvdata.format = (rxmessage.RTR == CAN_RTR_DATA) ? CAN_DATA_FORMAT : CAN_REMO_FORMAT;
        recvdata.dlc    = (rxmessage.DLC);
        
        for (j = 0; j < rxmessage.DLC; j++) {
            recvdata.data[j] = rxmessage.Data[j];
        }
        
        WriteLoopData_INT(&s_canctrlbk.rx_buf, &recvdata);
    }
    
    if (CAN_GetITStatus(CAN, CAN_IT_TME) != RESET) {                           /* 数据发送中断 */
        CAN_ClearITPendingBit(CAN, CAN_IT_TME);
        
        if (((s_canctrlbk.status & _COMOPEN) == 0) || ((s_canctrlbk.status & _SENDING) == 0)) {
            CAN_ITConfig((CAN_TypeDef *)CAN_BASE, CAN_IT_TME, DISABLE);        /* 关闭发送中断 */
        } else {
            used = UsedOfLoopBuffer_INT(&s_canctrlbk.tx_buf);
            if (used == 0) {                                                   /* 无数据要发送 */
                s_canctrlbk.status &= (~_SENDING);
                CAN_ITConfig((CAN_TypeDef *)CAN_BASE, CAN_IT_TME, DISABLE);    /* 关闭发送中断 */
            } else {
                ReadLoopData_INT(&s_canctrlbk.tx_buf, &recvdata);
                StartCanSend(&recvdata);
            }
        }
    }
}

/**************************************************************************************************
**  函数名称:  CAN_PINConfig
**  功能描述:  管脚配置
**  输入参数:  onoff:  打开/关闭, TRUE-打开串口, FALSE-关闭串口
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void CAN_PINConfig(INT8U onoff)
{
    GPIO_InitTypeDef gpio_initstruct;
        
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);                        /* 开启GPIO系统时钟 */
    
    gpio_initstruct.GPIO_Pin   = (INT16U)(1 << GPIO_PinSource9);
    gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;
    gpio_initstruct.GPIO_OType = GPIO_OType_PP;
    gpio_initstruct.GPIO_PuPd  = GPIO_PuPd_UP;
    
    if (onoff) {
        gpio_initstruct.GPIO_Mode  = GPIO_Mode_AF;
        GPIO_Init((GPIO_TypeDef *)GPIOB_BASE, &gpio_initstruct);
        GPIO_PinAFConfig((GPIO_TypeDef *)GPIOB_BASE, GPIO_PinSource9, GPIO_AF_4);
    } else {
        gpio_initstruct.GPIO_Mode  = GPIO_Mode_OUT;
        GPIO_Init((GPIO_TypeDef *)GPIOB_BASE, &gpio_initstruct);
        GPIO_ResetBits((GPIO_TypeDef *)GPIOB_BASE, (INT16U)(1 << GPIO_PinSource9));
    }
    
    gpio_initstruct.GPIO_Pin   = (INT16U)(1 << GPIO_PinSource8);
    gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;
    gpio_initstruct.GPIO_OType = GPIO_OType_PP;
    gpio_initstruct.GPIO_PuPd  = GPIO_PuPd_UP;
    
    if (onoff) {
        gpio_initstruct.GPIO_Mode  = GPIO_Mode_AF;
        GPIO_Init((GPIO_TypeDef *)GPIOB_BASE, &gpio_initstruct);
        GPIO_PinAFConfig((GPIO_TypeDef *)GPIOB_BASE, GPIO_PinSource8, GPIO_AF_4);
    } else {
        gpio_initstruct.GPIO_Mode  = GPIO_Mode_OUT;
        GPIO_Init((GPIO_TypeDef *)GPIOB_BASE, &gpio_initstruct);
        GPIO_ResetBits((GPIO_TypeDef *)GPIOB_BASE, (INT16U)(1 << GPIO_PinSource8));
    }
}

/**************************************************************************************************
**  函数名称:  CAN_IRQConfig
**  功能描述:  配置中断功能
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void CAN_IRQConfig(void)
{
    IRQ_ConfigEnable(CEC_CAN_IRQn, false);
    IRQ_InstallHandler(CEC_CAN_IRQn, (IRQ_SERVICE_FUNC)CAN_IrqHandle);
    IRQ_ConfigPriority(CEC_CAN_IRQn, IRQ_PRIOTITY_CAN);
    IRQ_ConfigEnable(CEC_CAN_IRQn, true);
    
    CAN_ITConfig((CAN_TypeDef *)CAN_BASE, CAN_IT_FMP0 | CAN_IT_FMP1, ENABLE);
}

/**************************************************************************************************
**  函数名称:  CAN_DrvConfig
**  功能描述:  CAN总线初始化(对CAN_Init函数的重新实现)
**  输入参数:  CANx: 寄存器结构体; can_initstruct: 参数结构体
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static INT8U CAN_DrvConfig(CAN_TypeDef *CANx, CAN_InitTypeDef *can_initstruct)
{
    INT32U ct_delay = 0x00000000;
    
    CANx->MCR &= (~(INT32U)CAN_MCR_SLEEP);
    CANx->MCR |= CAN_MCR_INRQ;
    
    while (++ct_delay < 0x100) {
        if ((CANx->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) {
            break;
        }
    }
    
    if ((CANx->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) {
        return CAN_InitStatus_Failed;
    }
    
    if (can_initstruct->CAN_TTCM == ENABLE) {
        CANx->MCR |= CAN_MCR_TTCM;
    } else {
        CANx->MCR &= ~(INT32U)CAN_MCR_TTCM;
    }

    if (can_initstruct->CAN_ABOM == ENABLE) {
        CANx->MCR |= CAN_MCR_ABOM;
    } else {
        CANx->MCR &= ~(INT32U)CAN_MCR_ABOM;
    }

    if (can_initstruct->CAN_AWUM == ENABLE) {
        CANx->MCR |= CAN_MCR_AWUM;
    } else {
        CANx->MCR &= ~(INT32U)CAN_MCR_AWUM;
    }

    if (can_initstruct->CAN_NART == ENABLE) {
        CANx->MCR |= CAN_MCR_NART;
    } else {
        CANx->MCR &= ~(INT32U)CAN_MCR_NART;
    }

    if (can_initstruct->CAN_RFLM == ENABLE) {
        CANx->MCR |= CAN_MCR_RFLM;
    } else {
        CANx->MCR &= ~(INT32U)CAN_MCR_RFLM;
    }

    if (can_initstruct->CAN_TXFP == ENABLE) {
        CANx->MCR |= CAN_MCR_TXFP;
    } else {
        CANx->MCR &= ~(INT32U)CAN_MCR_TXFP;
    }

    /* Set the bit timing register */
    CANx->BTR = (INT32U)((INT32U)can_initstruct->CAN_Mode << 30) | \
                ((INT32U)can_initstruct->CAN_SJW << 24) | \
                ((INT32U)can_initstruct->CAN_BS1 << 16) | \
                ((INT32U)can_initstruct->CAN_BS2 << 20) | \
               ((INT32U)can_initstruct->CAN_Prescaler - 1);

    /* Request leave initialisation */
    CANx->MCR &= ~(INT32U)CAN_MCR_INRQ;

    ct_delay = 0;
    while (++ct_delay < 0x100) {
        if ((CANx->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) {
            break;
        }
    }
    
    if ((CANx->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) {
        return CAN_InitStatus_Failed;
    }
    
    return CAN_InitStatus_Success;
}

/**************************************************************************************************
**  函数名称:  CAN_InitConfig
**  功能描述:  串口通信参数配置，并设置是否支持DMA
**  输入参数:  cfg: 串口配置参数 
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static BOOLEAN CAN_InitConfig(CAN_CONFIG_T *cfg)
{
    INT8U  result = false;
    INT32U baud;
    CAN_InitTypeDef can_initstruct;
	
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);
    
	CAN_StructInit(&can_initstruct);
    can_initstruct.CAN_TTCM = DISABLE;
    can_initstruct.CAN_ABOM = ENABLE;
    can_initstruct.CAN_AWUM = ENABLE;
    can_initstruct.CAN_NART = ENABLE;
    can_initstruct.CAN_RFLM = DISABLE;
    can_initstruct.CAN_TXFP = DISABLE;
    
    switch (cfg->mode)
    {
        case CAN_WKMODE_NORMAL:
            can_initstruct.CAN_Mode = CAN_Mode_Normal;
            break;
            
        case CAN_WKMODE_LOOPBACK:
            can_initstruct.CAN_Mode = CAN_Mode_LoopBack;
            break;
            
        case CAN_WKMODE_SILENT:
            can_initstruct.CAN_Mode = CAN_Mode_Silent;
            break;
            
        case CAN_WKMODE_STLPBK:
            can_initstruct.CAN_Mode = CAN_Mode_Silent_LoopBack;
            break;
            
        default:
            can_initstruct.CAN_Mode = CAN_Mode_Normal;
            break;
    }
    
    baud = cfg->baud;
    
    can_initstruct.CAN_SJW = CAN_SJW_1tq;
    can_initstruct.CAN_BS1 = CAN_BS1_15tq;
    can_initstruct.CAN_BS2 = CAN_BS2_8tq;
    can_initstruct.CAN_Prescaler = 2 * (1000000 / baud);
	
    result = CAN_DrvConfig((CAN_TypeDef *)CAN_BASE, &can_initstruct);
    
    if (result == CAN_InitStatus_Success) {
        result = TRUE;
        CAN_IRQConfig();
    } else {
        result = FALSE;
    }
    
    return result;
}

/**************************************************************************************************
**  函数名称:  DAL_CAN_Init
**  功能描述:  初始化驱动
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void DAL_CAN_Init(void)
{
    memset(&s_canctrlbk, 0, sizeof(s_canctrlbk));
}

/**************************************************************************************************
**  函数名称:  DAL_CAN_OpenCan
**  功能描述:  打开CAN通信总线
**  输入参数:  cfg: 配置参数 
**  输出参数:  无
**  返回参数:  成功返回true,失败返回false
**************************************************************************************************/
BOOLEAN DAL_CAN_OpenCan(CAN_CONFIG_T *cfg)
{
    SYS_ASSERT((cfg != 0), RETURN_FALSE);
    
    if ((s_canctrlbk.status & _COMOPEN) != 0) {                                /* 已打开 */
        s_canctrlbk.status &= ~(_COMOPEN | _SENDING);
	    CAN_DeInit((CAN_TypeDef *)CAN_BASE);
    }
    
    s_canctrlbk.rx_buf.pmsg = &s_can_rxbuf[0];                                 /* 接收缓存 */
    s_canctrlbk.rx_buf.used = 0;
    s_canctrlbk.rx_buf.pos  = 0;
    s_canctrlbk.rx_buf.max  = MAX_CAN_RECV;
    
    s_canctrlbk.tx_buf.pmsg = &s_can_txbuf[0];                                 /* 发送缓存 */
    s_canctrlbk.tx_buf.used = 0;
    s_canctrlbk.tx_buf.pos  = 0;
    s_canctrlbk.tx_buf.max  = MAX_CAN_SEND;
    
    CAN_PINConfig(TRUE);
    
    if (CAN_InitConfig(cfg)) {                                                 /* 通信参数配置 */
        s_canctrlbk.status = _COMOPEN;
        return true;
    } else {
        return false;
    }
}

/**************************************************************************************************
**  函数名称:  DAL_CAN_CloseCan
**  功能描述:  关闭CAN总线
**  输入参数:  无
**  输出参数:  无
**  返回参数:  成功返回true, 失败返回false
**************************************************************************************************/
BOOLEAN DAL_CAN_CloseCan(void)
{
    CAN_PINConfig(FALSE);
    
    if ((s_canctrlbk.status & _COMOPEN) != 0) {
        CAN_DeInit((CAN_TypeDef *)CAN_BASE);
    }
    
    s_canctrlbk.status &= ~(_COMOPEN | _SENDING);
    
    return true;
}

/**************************************************************************************************
**  函数名称:  DAL_CAN_IsOpened
**  功能描述:  通道是否已打开
**  输入参数:  无
**  输出参数:  无
**  返回参数:  是返回true,否返回false
**************************************************************************************************/
BOOLEAN DAL_CAN_IsOpened(void)
{
    if ((s_canctrlbk.status &_COMOPEN) != 0) {
        return true;
    } else {
        return false;
    }
}

/**************************************************************************************************
**  函数名称:  DAL_CAN_SetFilterParaByList
**  功能描述:  设置滤波参数 [设置滤波ID列表过滤方式]
**  输入参数:  idtype:    帧ID类型,见 CAN_DTTYPE_E
**  输入参数:  idnum:     滤波ID个数,为0时表示接收所有ID
**  输入参数:  pfilterid: 滤波ID数组
**  输出参数:  无
**  返回参数:  成功返回true, 失败返回false
**************************************************************************************************/
BOOLEAN DAL_CAN_SetFilterParaByList(INT8U idtype, INT8U idnum, INT32U *pfilterid)
{
    INT8U i;
    INT32U filterid;
    CAN_FilterInitTypeDef  can_filterinitstructure;
    
    if ((s_canctrlbk.status & _COMOPEN) == 0) {
        return false;
    }
    
    if (idtype == CAN_STD_FAMRE) {                                             /* 标准帧 */
        can_filterinitstructure.CAN_FilterMode           = CAN_FilterMode_IdList;
        can_filterinitstructure.CAN_FilterScale          = CAN_FilterScale_16bit;
        can_filterinitstructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
        can_filterinitstructure.CAN_FilterActivation     = ENABLE;
        
        for (i = 0; i < idnum && i < LIST_STD_FILTER; i++) {
            filterid = pfilterid[i] << 5;
            
            if ((i % 4) == 0) {
                can_filterinitstructure.CAN_FilterIdHigh     = filterid & 0xFFFF;
                can_filterinitstructure.CAN_FilterIdLow      = filterid & 0xFFFF;
                can_filterinitstructure.CAN_FilterMaskIdHigh = filterid & 0xFFFF;
                can_filterinitstructure.CAN_FilterMaskIdLow  = filterid & 0xFFFF;
                can_filterinitstructure.CAN_FilterNumber     = i / 4;
            } else if ((i % 4) == 1) {
                can_filterinitstructure.CAN_FilterIdLow      = filterid & 0xFFFF;
            } else if ((i % 4) == 2) {
                can_filterinitstructure.CAN_FilterMaskIdHigh = filterid & 0xFFFF;
            } else if ((i % 4) == 3) {
                can_filterinitstructure.CAN_FilterMaskIdLow  = filterid & 0xFFFF;
                can_filterinitstructure.CAN_FilterNumber     = i / 4;
                CAN_FilterInit(&can_filterinitstructure);
            }
        }
        
        if ((i % 4) != 0) {
            CAN_FilterInit(&can_filterinitstructure);
        }
        
        for (i = (i + 3) / 4; i < MAX_FILTER_BANK; i++) {                      /* 关闭剩余滤波器组 */
            can_filterinitstructure.CAN_FilterActivation = DISABLE;
            can_filterinitstructure.CAN_FilterNumber     = i;
            CAN_FilterInit(&can_filterinitstructure);
        }
    } else {
        can_filterinitstructure.CAN_FilterMode           = CAN_FilterMode_IdList;
        can_filterinitstructure.CAN_FilterScale          = CAN_FilterScale_32bit;
        can_filterinitstructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
        can_filterinitstructure.CAN_FilterActivation     = ENABLE;
            
        for (i = 0; i < idnum && i < LIST_EXT_FILTER; i++) {
            filterid = (pfilterid[i] << 3) | 0x04;                             /* 0x04表示扩展帧 */
            
            if ((i % 2) == 0) {
                can_filterinitstructure.CAN_FilterIdHigh     = (filterid >> 16) & 0xFFFF;
                can_filterinitstructure.CAN_FilterIdLow      = filterid & 0xFFFF;
                can_filterinitstructure.CAN_FilterMaskIdHigh = (filterid >> 16) & 0xFFFF;
                can_filterinitstructure.CAN_FilterMaskIdLow  = filterid & 0xFFFF;
                can_filterinitstructure.CAN_FilterNumber     = i / 2;
            } else {
                can_filterinitstructure.CAN_FilterMaskIdHigh = (filterid >> 16) & 0xFFFF;
                can_filterinitstructure.CAN_FilterMaskIdLow  = filterid & 0xFFFF;
                can_filterinitstructure.CAN_FilterNumber     = i / 2;
                CAN_FilterInit(&can_filterinitstructure);
            }
        }
        
        if ((i % 2) != 0) {
            CAN_FilterInit(&can_filterinitstructure);
        }
        
        for (i = (i + 1) / 2; i < MAX_FILTER_BANK; i++) {                      /* 关闭剩余滤波器组 */
            can_filterinitstructure.CAN_FilterActivation = DISABLE;
            can_filterinitstructure.CAN_FilterNumber     = i;
            CAN_FilterInit(&can_filterinitstructure);
        }
    }
    
    if (idnum == 0) {                                                          /* 滤波ID个数为0,表示不滤波,接收所有数据帧 */
        can_filterinitstructure.CAN_FilterMode       = CAN_FilterMode_IdMask;
        can_filterinitstructure.CAN_FilterActivation = ENABLE;
        can_filterinitstructure.CAN_FilterIdHigh     = 0;
        can_filterinitstructure.CAN_FilterIdLow      = 0;
        can_filterinitstructure.CAN_FilterMaskIdHigh = 0;
        can_filterinitstructure.CAN_FilterMaskIdLow  = 0;
        can_filterinitstructure.CAN_FilterNumber     = 0;
        CAN_FilterInit(&can_filterinitstructure);
    }
    
    return true;
}

/**************************************************************************************************
**  函数名称:  DAL_CAN_SetFilterParaByMask
**  功能描述:  设置滤波参数 [设置滤波ID掩码过滤方式]
**  输入参数:  idtype:   帧ID类型,见 CAN_DTTYPE_E
**  输入参数:  idnum:    滤波ID个数,为0时表示接收所有ID
**  输入参数:  pfilterid: 滤波ID数组
**  输入参数:  pmaskid:   掩码ID数组
**  输出参数:  无
**  返回参数:  成功返回true, 失败返回false
**************************************************************************************************/
BOOLEAN DAL_CAN_SetFilterParaByMask(INT8U idtype, INT8U idnum, INT32U *pfilterid, INT32U *pmaskid)
{
    INT8U i;
    INT32U filterid, maskid;
    CAN_FilterInitTypeDef  can_filterinitstructure;
    
    if ((s_canctrlbk.status & _COMOPEN) == 0) {
        return false;
    }
    
    if (idtype == CAN_STD_FAMRE) {
        can_filterinitstructure.CAN_FilterMode           = CAN_FilterMode_IdMask;
        can_filterinitstructure.CAN_FilterScale          = CAN_FilterScale_16bit;
        can_filterinitstructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
        can_filterinitstructure.CAN_FilterActivation     = ENABLE;
        
        for (i = 0; i < idnum && i < MASK_STD_FILTER; i++) {
            filterid = pfilterid[i] << 5;
            maskid   = (pmaskid[i] << 5) | 0x08;                               /* 0x08需要掩码标准帧位 */
            
            if ((i % 2) == 0) {
                can_filterinitstructure.CAN_FilterIdHigh     = filterid & 0xFFFF;
                can_filterinitstructure.CAN_FilterMaskIdHigh = maskid & 0xFFFF;
                can_filterinitstructure.CAN_FilterIdLow      = filterid & 0xFFFF;
                can_filterinitstructure.CAN_FilterMaskIdLow  = maskid & 0xFFFF;
                can_filterinitstructure.CAN_FilterNumber     = i / 2;
            } else {
                can_filterinitstructure.CAN_FilterIdLow      = filterid & 0xFFFF;
                can_filterinitstructure.CAN_FilterMaskIdLow  = maskid & 0xFFFF;
                can_filterinitstructure.CAN_FilterNumber     = i / 2;
                CAN_FilterInit(&can_filterinitstructure);
            }
        }
        
        if ((i % 2) != 0) {
            CAN_FilterInit(&can_filterinitstructure);
        }
        
        for (i = (i + 1) / 2; i < MAX_FILTER_BANK; i++) {               /* 关闭剩余滤波器组 */
            can_filterinitstructure.CAN_FilterActivation = DISABLE;
            can_filterinitstructure.CAN_FilterNumber     = i;
            CAN_FilterInit(&can_filterinitstructure);
        }
    } else {
        can_filterinitstructure.CAN_FilterMode           = CAN_FilterMode_IdMask;
        can_filterinitstructure.CAN_FilterScale          = CAN_FilterScale_32bit;
        can_filterinitstructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
        can_filterinitstructure.CAN_FilterActivation     = ENABLE;
            
        for (i = 0; i < idnum && i < MASK_EXT_FILTER; i++) {
            filterid = (pfilterid[i] << 3) | 0x04;                             /* 0x04表示扩展帧 */
            maskid   = (pmaskid[i] << 3) | 0x04;
            
            can_filterinitstructure.CAN_FilterIdHigh     = (filterid >> 16) & 0xFFFF;
            can_filterinitstructure.CAN_FilterIdLow      = filterid & 0xFFFF;
            can_filterinitstructure.CAN_FilterMaskIdHigh = (maskid >> 16) & 0xFFFF;
            can_filterinitstructure.CAN_FilterMaskIdLow  = maskid & 0xFFFF;
            can_filterinitstructure.CAN_FilterNumber     = i;
            CAN_FilterInit(&can_filterinitstructure);
        }
        
        for (; i < MAX_FILTER_BANK; i++) {                              /* 关闭剩余滤波器组 */
            can_filterinitstructure.CAN_FilterActivation = DISABLE;
            can_filterinitstructure.CAN_FilterNumber     = i;
            CAN_FilterInit(&can_filterinitstructure);
        }
    }
    
    if (idnum == 0) {                                                          /* 滤波ID个数为0,表示不滤波,接收所有数据帧 */
        can_filterinitstructure.CAN_FilterMode       = CAN_FilterMode_IdMask;
        can_filterinitstructure.CAN_FilterActivation = ENABLE;
        can_filterinitstructure.CAN_FilterIdHigh     = 0;
        can_filterinitstructure.CAN_FilterIdLow      = 0;
        can_filterinitstructure.CAN_FilterMaskIdHigh = 0;
        can_filterinitstructure.CAN_FilterMaskIdLow  = 0;
        can_filterinitstructure.CAN_FilterNumber     = 0;
        CAN_FilterInit(&can_filterinitstructure);
    }
    
    return true;
}

/**************************************************************************************************
**  函数名称:  DAL_CAN_ReadData
**  功能描述:  读取一帧数据
**  输入参数:  无
**  输出参数:  data: 数据帧
**  返回参数:  成功返回数据，失败返回-1
**************************************************************************************************/
BOOLEAN DAL_CAN_ReadData(CAN_DATA_T *data)
{
    if ((s_canctrlbk.status & _COMOPEN) == 0) {
        return false;
    }
    
    return ReadLoopData(&s_canctrlbk.rx_buf, data);
}

/**************************************************************************************************
**  函数名称:  DAL_CAN_SendData
**  功能描述:  发送一帧数据
**  输入参数:  data: 数据帧
**  输出参数:  无
**  返回参数:  成功返回true,失败返回false
**************************************************************************************************/
BOOLEAN DAL_CAN_SendData(CAN_DATA_T *data)
{
    INT8U            result;
    CAN_DATA_T       candata;
    
    if ((s_canctrlbk.status & _COMOPEN) == 0) {
        return FALSE;
    }
    
    result = WriteLoopData(&s_canctrlbk.tx_buf, data);
    
    ENTER_CRITICAL();
    if ((s_canctrlbk.status & _SENDING) == 0) {
        EXIT_CRITICAL();
        
        CAN_ITConfig((CAN_TypeDef *)CAN_BASE, CAN_IT_TME, DISABLE);            /* 关闭发送中断 */
        
        CAN_CancelTransmit((CAN_TypeDef *)CAN_BASE, 0);
        CAN_CancelTransmit((CAN_TypeDef *)CAN_BASE, 1);
        CAN_CancelTransmit((CAN_TypeDef *)CAN_BASE, 2);
        
        ReadLoopData_INT(&s_canctrlbk.tx_buf, &candata);
        if (StartCanSend(&candata) == TRUE) {
            s_canctrlbk.status |= _SENDING;
            CAN_ITConfig((CAN_TypeDef *)CAN_BASE, CAN_IT_TME, ENABLE);         /* 打开发送中断 */
        }
    } else {
        EXIT_CRITICAL();
    }
    
    return result;
}

/**************************************************************************************************
**  函数名称:  DAL_CAN_UsedOfRecvbuf
**  功能描述:  获取已接收帧数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  已接收数据帧数
**************************************************************************************************/
INT32U DAL_CAN_UsedOfRecvbuf(void)
{
    if ((s_canctrlbk.status & _COMOPEN) == 0) {
        return 0;
    }
    
    return UsedOfLoopBuffer(&s_canctrlbk.rx_buf);
}

/**************************************************************************************************
**  函数名称:  DAL_CAN_LeftOfSendbuf
**  功能描述:  获取发送缓存剩余空间
**  输入参数:  无
**  输出参数:  无
**  返回参数:  剩余数据帧数
**************************************************************************************************/
INT32U DAL_CAN_LeftOfSendbuf(void)
{
    if ((s_canctrlbk.status & _COMOPEN) == 0) {
        return 0;
    }
    
    return LeftOfLoopBuffer(&s_canctrlbk.tx_buf);
}

/**************************************************************************************************
**  函数名称:  DAL_CAN_GetStatus
**  功能描述:  获取CAN总线状态
**  输入参数:  无
**  输出参数:  info: 状态信息,见 CAN_STATUS_T
**  返回参数:  成功返回true, 失败返回false
**************************************************************************************************/
BOOLEAN DAL_CAN_GetStatus(CAN_STATUS_T *info)
{
    info->stt = DAL_CAN_IsOpened();
    info->lec = (CAN_ERRTYP_E)CAN_GetLastErrorCode((CAN_TypeDef *)CAN_BASE) >> 4;
    info->rec = CAN_GetReceiveErrorCounter((CAN_TypeDef *)CAN_BASE);
    info->tec = CAN_GetLSBTransmitErrorCounter((CAN_TypeDef *)CAN_BASE);
    
    if (CAN_GetFlagStatus((CAN_TypeDef *)CAN_BASE, CAN_FLAG_BOF) == SET) {/* 总线关闭 */
        info->err = CAN_ERR_STAT_BUSOFF;
    } else if (CAN_GetFlagStatus((CAN_TypeDef *)CAN_BASE, CAN_FLAG_EPV) == SET) {/* 被动错误 */
        info->err = CAN_ERR_STAT_PASSIVE;
    } else if (CAN_GetFlagStatus((CAN_TypeDef *)CAN_BASE, CAN_FLAG_EWG) == SET) {/* 错误警告 */
        info->err = CAN_ERR_STAT_WARNING;
    } else if (info->rec > 0 && info->tec > 0) {                               /* 主动错误 */
        info->err = CAN_ERR_STAT_ACTIVE;
    } else {
        info->err = CAN_ERR_STAT_NOERR;
    }
    
    return true;
}


